package com.link2room.rodimus.service.impl;

import com.link2room.common.constant.DefaultValue;
import com.link2room.common.dao.ICommonDao;
import com.link2room.common.entity.BaseEntity;
import com.link2room.common.exception.SysException;
import com.link2room.common.service.ICommonService;
import com.link2room.rodimus.entity.ExpressBaseEntity;
import com.link2room.rodimus.service.IExpressService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

import static com.link2room.enums.exception.RodimusSysExceptionEnum.EXPRESS_ERROR;


/**
 * Created by LN on 2017/7/28.10:52
 */
@Component("expressService")
public class ExpressServiceImpl implements IExpressService {
    @Autowired
    private RedisLockRegistry expressLock;
    @Resource
    private ICommonService commonService;
    @Resource
    private ICommonDao commonDao;

    private static final String EXP_NO="EXP_NO";
    @Override
    public ExpressBaseEntity initExpress() throws Exception {
        ExpressBaseEntity e = new ExpressBaseEntity();
        e.setExpressNo(callProcedure(EXP_NO));
        e.setIsDelivered(DefaultValue.F);
        return e;
    }

    @Override
    @Transactional
    public <T extends BaseEntity>void saveExpress(ExpressBaseEntity exp, T updateSurece) throws Exception {
        commonDao.save(exp);
        commonDao.merge(updateSurece);
    }

    private String callProcedure(String lockKey) throws Exception {
        Lock lock = expressLock.obtain(lockKey);
        if (lock.tryLock(2, TimeUnit.SECONDS)) {
            try {
                List params = new ArrayList<>();
                params.add(lockKey);
                String no = commonService.findOneFieldByProcedure("create_No", params);
                return no;
            } finally {
                lock.unlock();
            }
        } else {
            throw new SysException(EXPRESS_ERROR, "生成" + lockKey + "异常,稍后重试");
        }
    }
}
